"""
!/usr/bin/env python
-*- coding: utf-8 -*-
@Author  : MarkJia
@Site    : 
@File    : 8、3种等待方式.py
"""

# ==============================  避免页面未渲染完成就操作，导致的错误。  ======================================
# ====================  no such element：unable to locate element ===================
# =========================== 可能原因：（1. 没找到元素-元素定位表达式写错，   2. 没加等待，   3. 窗口/iframe等） ===========================
"""
1、强制等待 ： 强制线程等待 - 调式代码，临时性添加
2、隐式等待 ： 在时间范围内，轮询查找元素 - 解决找不到元素问题，无法解决交互问题
  页面元素加载是异步加载过程，通常 html 会先加载完成，随后是 js  css
  元素存在与否是由 html 决定，元素的交互是由 css js 决定
3、显式等待 ： 设定特定的等待条件，轮询操作 - 解决特定条件的等待问题，比如点击等交互性行为
避免报错： NoSuchElementException：no such element：unable to locate element

"""

import time
from selenium.webdriver.common.by import By

# ===================   1：直接等待。与 selenium 没关系。一般不常用  ==========================
# 强制等待，线程休眠。界面渲染需要一定时间，等待页面渲染完成
# 等待时间过长，而影响用例的执行效率。等待时间过短，元素未加载，导致代码报错
time.sleep(3)

# ===========================   2、隐式等待。每隔默认 0.5s 轮询查找，如果元素在设定时间内没找到，会抛出异常 =================
# 就是在创建 driver 时，为浏览器对象创建一个等待时间，这个方法是找不到某一个元素就等待，直到拿到这个元素为止
from selenium import webdriver

driver = webdriver.Chrome()
driver.get('https://www.baidu.com')
driver.maximize_window()
#  =======================  设置隐式等待，只能等待元素加载。全局一次设置，作用于所有 find_element 方法 ===============
driver.implicitly_wait(10)
driver.find_element(By.ID, 'kw')

# 3、显式等待：指定具体某一个操作。 明确要等待某个元素的出现或者某个元素可点击事件（隐式等待只关注元素能不能找到，不关注元素能否点击或者进行其他的交互）
# 页面元素加载是异步加载过程，通常 html 会先加载完成，随后是 js  css
# 元素存在与否是由 html 决定，元素的交互是由 css js 决定

"""
在代码中定义等待条件，当条件发生时才继续执行代码
webDriverWait 配合 until() 和 until_not() 使用，根据判断条件进行等待
程序每隔 0.5s 进行条件判断，如果条件成立，则执行下一步。否则继续等待，直到超出最大设定时间
"""

from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions

driver = webdriver.Chrome()
driver.get('https://www.baidu.com')
# 设置显示等待：搜索框元素
# ==================================  等待元素是否存在页面中，expected_conditions 的参数传入都是一个元组 ===========================
# ==================================  判断元素是否加载 =======================================
element = WebDriverWait(driver, 4, 0.5).until(expected_conditions.presence_of_element_located((By.ID, 'kw')))
# ==================================  等待元素是否可见  =======================================
element1 = WebDriverWait(driver, 4, 0.5).until(expected_conditions.visibility_of_element_located((By.ID, 'kw')))
# ================================== 等待元素是否可以被点击 =====================================
element2 = WebDriverWait(driver, 4, 0.5).until(expected_conditions.element_to_be_clickable((By.ID, 'su')))

element.send_keys('python')
driver.quit()

# 显示等待常用的两个类 ：
# 一是 WebDriverWait 和 expected_conditions 两个类
# WebDriverWait(driver,timeout=10,poll_frequency=0.5,ignored_exceptions=None)
"""
driver ： 浏览器驱动
timeout ： 最长超时时间，默认以秒为单位
poll_frequency ： 轮询时间，默认为0.5秒
ignored_exceptions ： 超时后的异常信息，默认情况下抛 NosuchElementException 异常
WebDriverWait 一般有 until 和 until_not 方法配合使用
"""

# until(method,message)
"""
method ： 在等待期间，每隔一段时间调用该传入的方法，直到返回值不是 False
message ： 超时会抛出 ： TimeoutException，将 message 传入异常
"""

# 二是：expected_conditions 类
"""
presence_of_element_located ： 判断某一个元素是否被加到了DOM树里，并不代表该元素一定可见
visibility_of_element_located ： 判断元素是否可见
element_to_be_clickable : 判断元素是否可以被点击
"""

import time


class TestWait:
    def setup(self):
        self.driver = webdriver.Chrome()
        self.driver.get('https://www.baidu.com')
        # 隐式等待
        self.driver.implicitly_wait(10)
        self.driver.maximize_window()

    # 直接等待  百度输入python，等待2s后，点击
    def test_wait(self):
        self.driver.find_element(By.ID, 'kw').clear()
        self.driver.find_element(By.ID, 'kw').send_keys('python')
        # 强制等待
        time.sleep(2)

        # 显示等待 : 直到百度一下元素可被点击
        WebDriverWait(self.driver, 10).until(expected_conditions.element_to_be_clickable((By.ID, 'su'))).click()

    def teardown(self):
        self.driver.quit()


# 显性等待 ： 点击消息提示 -> 弹出：这是一条消息提示
from selenium.webdriver.support import expected_conditions


def test_wait_show():
    driver = webdriver.Chrome()
    driver.get('https://vip.ceshiren.com/#/ui_study')
    # 等待元素是否可以被点击，expected_conditions 的参数传入都是一个元组
    WebDriverWait(driver, 10).until(
        expected_conditions.element_to_be_clickable((By.CSS_SELECTOR, '#success_btn'))).click()
